const h = (tag,props,children)=>{
  // vnode -> javascript对象 -> {}
  return {
    tag,
    props,
    children
  }
}

// 挂载
const mount = (vnode,container) =>{
  // vnode -> element
  // 1.创建出真实的元素，并且在vnode上保留el
  const el = vnode.el = document.createElement(vnode.tag)

  // 2.把属性添加到元素上
  // 处理props
  if(vnode.props){
    for(const key in vnode.props){
      const value = vnode.props[key]

      // 边界判断 
      if(key.startsWith("on")){
        // 事件监听
        el.addEventListener(key.slice(2).toLowerCase(),value)
      }else{
        el.setAttribute(key,value)
      }

    }
  }

  // 3.处理子节点children
  // 简易写：字符串 or 数组
  if(vnode.children){
    if(typeof vnode.children === "string"){
      el.textContent = vnode.children
    }else {
      vnode.children.forEach(item =>{
        // 递归
        // 挂载到el上面
        mount(item,el)
      })
    }
  }

  // 4.将el挂载到container中
  container.appendChild(el)

}

// patch函数
// 通过patch方法把新旧vnode进行Diff算法
const patch =(n1,n2)=>{
  // diff算法
  if(n1.tag !== n2.tag){
    // 拿到元素的父元素，移除父元素中的子元素
    const n1ElParent = n1.el.parentElement
    n1ElParent.removeChild(n1.el)
    mount(n2,n1ElParent)
  }else{
    // 1.取出element对象,并且在n2中进行保存
    const el = n2.el = n1.el

    // 2.处理props属性
    const oldProps = n1.props || {}
    const newProps = n2.props || {}
    // 2.1获取所有的newProps添加到el里面
    for(const key in newProps){
      const oldValue = oldProps[key]
      const newValue = newProps[key]
      if(newValue !== oldValue) {
        if(key.startsWith("on")){
          el.addEventListener(key.slice(2).toLowerCase(),newValue)
        }else{
          el.setAttribute(key,newValue)
        }
      }
    }

    // 2.2删除旧的props
    for(const key in oldProps){

      if(key.startsWith("on")){
        const value = oldProps[key]
        el.removeEventListener(key.slice(2).toLowerCase(),value)
      }
      
      if(!(key in newProps)){
        el.removeAttribute(key)
      }
    }

    // 3.处理children子元素
    const oldChildren = n1.children || [] 
    const newChildren = n2.children || [] 

    // 情况一 newChildren本身是一个字符串
    if(typeof newChildren === 'string'){
      // 边界情况
      if(typeof oldChildren === 'string'){
        if(newChildren !== oldChildren){
          el.textContent = newChildren
        }
      } else {
        el.innerHTML = newChildren
      }
      
    } else { //情况二 newChildren不是string
      // 数组
      if(typeof oldChildren === 'string'){
        el.innerHTML = ""
        newChildren.forEach(item =>{
          mount(item,el)
        })
      }else{
        //oldChildren:[v1,v2,v3]
        //newChildren:[v1,v2,v3,v4,v5,v6]
        // 1.前面有相同节点的原生进行patch操作
        const commonLength = Math.min(oldChildren.length,newChildren.length)
        for(let i=0;i<commonLength;i++){
          patch(oldChildren[i],newChildren[i])
        }

        // 2.newChildren.length > oldChildren.length
        if(newChildren.length > oldChildren.length){
          newChildren.slice(oldChildren.length).forEach(item=>{
            mount(item,el)
          })
        }

        // 3. newChildren.length < oldChildren.length
        if(newChildren.length < oldChildren.length){
          oldChildren.slice(newChildren.length).forEach(item=>{
            // 卸载
            el.removeChild(item.el)
          })
        }

      }
    }


  }

}
